/*
 * test.c
 *
 *  Created on: 2014年9月24日
 *      Author: chens
 */

#include "cm_mib_id.h"
#include "cm_mib.h"
#include <cm/struct/cm_stack.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

/*
 * @brief	从stdin读入构造一个node必须的数据
 */
static inline int scanf_node(cmmib_id *id, char *brief, char *data,
		unsigned *len)
{
	char temp[CMMIB_MAX_ID_LEN];
	printf("ID of node: ");
	fgets(temp, CMMIB_MAX_ID_LEN, stdin);
	*id = cmmib_str2id(temp, '.');
	if (id->level[0] == 0) {
		printf("error ID.\n");
		return -1;
	}
	printf("describe (128 char max): ");
	fgets(brief, MIB_ALLOC_SIZE - 1, stdin);
	if (brief[strlen(brief) - 1] == '\n') {
		brief[strlen(brief) - 1] = 0; // 去掉'\n'
	}

	printf("data: ");
	fgets(data, *len, stdin);
	*len = strlen(data);
	if (data[*len - 1] == '\n') {
		data[*len - 1] = 0; // 去掉'\n'
		(*len)--;
	}
	return 0;
}

static void new_node(struct cmmib_node * root)
{
	if (root == NULL) {
		printf("ROOT not seted.\n");
		return;
	}

	cmmib_id id;
	unsigned len = MIB_ALLOC_SIZE;
	char data[MIB_ALLOC_SIZE];
	char brief[MIB_ALLOC_SIZE];
	scanf_node(&id, brief, data, &len);

	struct cmmib_node *n = cmmib_newnode(id, brief, data, len);
	if (n == NULL) {
		printf("create node failed.\n");
		return;
	}

	if (cmmib_insert(n, root)) {
		printf("insert new node to root failed.\n");
		cmmib_delnode(&n);
		return;
	}
}

static void print_node(struct cmmib_node * root)
{
	if (root == NULL) {
		printf("ROOT not seted.\n");
		return;
	}

	char temp[CMMIB_MAX_ID_LEN];
	printf("Node print(ID): ");
	fgets(temp, CMMIB_MAX_ID_LEN, stdin);
	cmmib_id id = cmmib_str2id(temp, '.');

	struct cmmib_node *n = cmmib_find(id, root);
	if (n == NULL) {
		printf("Can't find this node.\n");
	} else {
		printf("\nbrief: %s\nvalue: %s\n", n->brief, n->data.bytes);
	}
}

static void print_title()
{
	printf("\nCommand(h for help): ");
}

static void print_help()
{
	printf("\nR    Set the ROOT node of mib tree.\n");
	printf("N    create a New node add insert into tree (or replace).\n");
	printf("C    show Current ROOT's name.\n");
	printf("A    show All children of one node.\n");
	printf("P    Print one node's value.\n");
	printf("S    Save this tree.\n");
	printf("L    Load tree from file.\n");
	printf("Q    Quit this program.\n\n");
}

static void inline print_root(struct cmmib_node * root)
{
	if (root == NULL) {
		printf("ROOT not seted.\n");
	} else {
		char temp[CMMIB_MAX_ID_LEN];
		cmmib_id2str(root->id, temp);
		printf("ROOT: %s\n", temp);
	}
}

static void _print_node(struct cmmib_node *node, void *arg)
{
	char temp[CMMIB_MAX_ID_LEN];
	cmmib_id2str(node->id, temp);
	int level = cmmib_level(node->id);
	while (level--)
		printf("    ");
	printf("|-- %s (%s)\n", temp, node->brief);
}

static void inline print_children(struct cmmib_node *root)
{
	if (root == NULL) {
		printf("ROOT not seted.\n");
		return;
	}

	char temp[CMMIB_MAX_ID_LEN];
	printf("Node for list children(ID): \n");
	fgets(temp, CMMIB_MAX_ID_LEN, stdin);
	cmmib_id id = cmmib_str2id(temp, '.');

	struct cmmib_node *n = cmmib_find(id, root);
	if (n == NULL) {
		printf("Can't find this node.\n");
	} else {
		for_each_node(n, _print_node, NULL);
	}
}

static void set_root(struct cmmib_node **ptr, struct cmmib_node * root)
{
	if (*ptr != NULL) {
		printf("ROOT is already seted.\n");
		return;
	}
	printf("You are setting up the root node.\n");
	root->len = sizeof(root->data.bytes);
	scanf_node(&(root->id), root->brief, root->data.bytes, &(root->len));

	*ptr = root;
}

int main()
{
	int cmd;
	struct cmmib_node root;
	struct cmmib_node *proot = NULL;
	memset(&root, 0, sizeof(root));
	do {
		print_title();
		cmd = getchar();
		if (cmd == '\n')
			continue;

		while (getchar() != '\n')
			;

		cmd = toupper(cmd);
		//printf("cmd = %d\n", cmd);
		switch (cmd) {
		case 'R':
			set_root(&proot, &root);
			break;
		case 'C':
			print_root(proot);
			break;
		case 'A':
			print_children(proot);
			break;
		case 'N':
			new_node(proot);
			break;
		case 'P':
			print_node(proot);
			break;
		case 'Q':
			printf("quit.\n");
			break;
		case 'H':
			print_help();
			break;
		case 'S':
			save_tree(proot, "mib.tree");
			break;
		case 'L':
			if (proot == NULL) {
				load_tree(&root, "mib.tree");
				proot = &root;
			} else {
				printf("ROOT is already seted.\n");
			}
			break;
		default:
			printf("Invalid command.\n");
		}
	} while (cmd != 'q' && cmd != 'Q');
}
